#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>

static char *gamename=NULL;
static char *romname;
static long picture=0;

static void fetchImage();
static void decodeGet(char *,long);
static void setArg(char *,char *,long);
static void fatal();

int main()
{
	int i;
	char *query;
	uint32_t len;

	// cache all images for 30 days.
	printf("Cache-Control: max-age=2592000, must-revalidate\n");

	query=getenv("QUERY_STRING");
	if (query==NULL) fatal();

	decodeGet(query,strlen(query));

	if (gamename==NULL) fatal();

	/* we're going to do the same sanitation we do in iffy.cgi */
	for (i=0;i<strlen(gamename);i++)
		if ((gamename[i]<'A' || gamename[i]>'Z') &&
		    (gamename[i]<'a' || gamename[i]>'z') &&
		    (gamename[i]<'0' || gamename[i]>'9') &&
		    gamename[i]!='.' && gamename[i]!='_')
		{
			gamename[i]=0;
			break;
		}
	
	len=20+strlen(gamename);
	romname=malloc(len);
	snprintf(romname,len,"roms/%s",gamename);

	fetchImage();
	return 0;
}

#define r32(x) ((buf[x]<<24)|(buf[x+1]<<16)|(buf[x+2]<<8)|buf[x+3])
static void fetchImage()
{
	uint32_t len;
	uint8_t buf[12];
	uint8_t *img;
	FILE *f;

	f=fopen(romname,"rb");
	if (f==NULL) fatal();

	fread(buf,4,1,f);
	if (r32(0)==0x464f524d) //blorb (FORM)
	{
		uint32_t numres,i;

		fseek(f,12,SEEK_SET);
		fread(buf,8,1,f);
		if (r32(0)!=0x52496478) //RIdx
			fatal();
		fread(buf,4,1,f);
		numres=r32(0);
		for (i=0;i<numres;i++)
		{
			fread(buf,12,1,f);
			if (r32(0)==0x50696374 && r32(4)==picture) //Pict
			{
				fseek(f,r32(8),SEEK_SET);
				break;
			}
		}
		fread(buf,8,1,f);
		if (r32(0)==0x4a504547) //JPEG
			printf("Content-Type: image/jpeg\n\n"); 
		else if (r32(0)==0x504e4720) //PNG
			printf("Content-Type: image/png\n\n");
		else fatal();
	}
	else fatal();

	len=r32(4);

	img=malloc(len);
	fread(img,len,1,f);
	fwrite(img,len,1,stdout);
	fclose(f);
}


static void decodeGet(char *get,long getlen)
{
	char *key;
	long i,value;
	int readval=0;
	key=get;
	for (i=0;i<getlen;i++)
	{
		if (get[i]=='=')
		{
			get[i]=0;
			readval=1;
			value=i+1;
		}
		if (get[i]=='&')
		{
			setArg(key,get+value,i-value);
			key=get+i+1;
			readval=0;
		}
	}
	if (readval) setArg(key,get+value,i-value);
}
static void setArg(char *key,char *evalue,long evaluelen)
{
	long i;
	char *value=malloc(evaluelen+1),*p;
	p=value;
	for (i=0;i<evaluelen;i++)
	{
		if (evalue[i]=='+') *p++=' ';
		else if (evalue[i]=='%')
		{
			int code;
			if (sscanf(evalue+i+1,"%2x",&code)!=1) code='?';
			*p++=code;
			i+=2;
		}
		else *p++=evalue[i];
	}
	*p++=0;
	if (!strcmp(key,"game")) gamename=strdup(value);
	else if (!strcmp(key,"picture")) sscanf(value,"%ld",&picture);
	free(value);
}
static unsigned char missing[]={
0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52,
0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x37,0x6e,0xf9,
0x24,0x00,0x00,0x00,0x02,0x62,0x4b,0x47,0x44,0x00,0x00,0xaa,0x8d,0x23,0x32,0x00,
0x00,0x00,0x09,0x70,0x48,0x59,0x73,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x48,0x00,
0x46,0xc9,0x6b,0x3e,0x00,0x00,0x00,0x09,0x76,0x70,0x41,0x67,0x00,0x00,0x00,0x01,
0x00,0x00,0x00,0x01,0x00,0xc7,0x95,0x5f,0xed,0x00,0x00,0x00,0x0a,0x49,0x44,0x41,
0x54,0x08,0xd7,0x63,0x68,0x00,0x00,0x00,0x82,0x00,0x81,0xdd,0x43,0x6a,0xf4,0x00,
0x00,0x00,0x00,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82};
static void fatal()
{
	printf("Content-Type: image/png\n\n");
	fwrite(missing,sizeof(missing),1,stdout);
	exit(0);
}
